Expand description
§Binggan (餅乾, bǐng gān) - A Benchmarking Library for Stable Rust
Binggan is a benchmarking library designed for flexibility, providing fast and stable results.
It reports peak memory consumption and can integrate with perf
for hardware performance counters.
§Main Components
Binggan has two primary entry points for running benchmarks:
- BenchRunner: A main runner for. Useful for single benchmarks or to create groups.
- InputGroup: Use this when running a group of benchmarks with the same inputs, where ownership of inputs can be transferred.
Otherwise if you need more flexibility you can use BenchGroup via BenchRunner::new_group.
See https://github.com/PSeitz/binggan/tree/main/benches for examples. benches/bench_group.rs
and
benches/bench_input_group.rs
are different ways to produce the same output.
§OutputValue
The typical benchmarking flow involves providing some input, processing it through a function, and obtaining an output. Benchmarks return OutputValue, which represents the result of the benchmark. This output can be particularly useful in scenarios like compression benchmarks, where it reports the output size or other relevant metrics.
§Plugins
See the plugins module for more information on how to register custom plugins.
§Reporting
See the report module for more information on how to customize the benchmark result reporting.
§Perf Integration
Binggan can integrate with perf to report hardware performance counters. See PerfCounterPlugin for more information.
§Example for InputGroup
use binggan::{black_box, InputGroup, PeakMemAlloc, INSTRUMENTED_SYSTEM, plugins::*};
#[global_allocator]
pub static GLOBAL: &PeakMemAlloc<std::alloc::System> = &INSTRUMENTED_SYSTEM;
fn main() {
// Tuples of name and data for the inputs
let data = vec![
(
"max id 100; 100 el all the same",
std::iter::repeat(100).take(100).collect(),
),
(
"max id 100; 100 el all different",
(0..100).collect()
),
];
bench_group(InputGroup::new_with_inputs(data));
}
// Run the benchmark for the group with input `Vec<usize>`
fn bench_group(mut runner: InputGroup<Vec<usize>, u64>) {
runner
// Set the peak mem allocator. This will enable peak memory reporting.
.add_plugin(PeakMemAllocPlugin::new(GLOBAL))
.add_plugin(PerfCounterPlugin::default());
runner.register("vec", move |data| {
let vec = test_vec(data);
vec.len() as u64
});
runner.register("hashmap", move |data| {
let map = test_hashmap(data);
map.len() as u64
});
runner.run();
}
fn test_vec(data: &Vec<usize>) -> Vec<usize> {
let mut vec = Vec::new();
for idx in data {
if vec.len() <= *idx {
vec.resize(idx + 1, 0);
}
vec[*idx] += 1;
}
black_box(vec)
}
fn test_hashmap(data: &Vec<usize>) -> std::collections::HashMap<usize, i32> {
let mut map = std::collections::HashMap::new();
for idx in data {
*map.entry(*idx).or_insert(0) += 1;
}
black_box(map)
}
§Example for BenchGroup
use std::collections::HashMap;
use binggan::{black_box, plugins::*, BenchRunner, PeakMemAlloc, INSTRUMENTED_SYSTEM};
#[global_allocator]
pub static GLOBAL: &PeakMemAlloc<std::alloc::System> = &INSTRUMENTED_SYSTEM;
fn test_vec(data: &Vec<usize>) -> Vec<i32> {
let mut vec = Vec::new();
for idx in data {
if vec.len() <= *idx {
vec.resize(idx + 1, 0);
}
vec[*idx] += 1;
}
vec
}
fn test_hashmap(data: &Vec<usize>) -> HashMap<&usize, i32> {
let mut map = std::collections::HashMap::new();
for idx in data {
*map.entry(idx).or_insert(0) += 1;
}
map
}
fn run_bench() {
let inputs: Vec<(&str, Vec<usize>)> = vec![
(
"max id 100; 100 el all the same",
std::iter::repeat(100).take(100).collect(),
),
("max id 100; 100 el all different", (0..100).collect()),
];
let mut runner: BenchRunner = BenchRunner::new();
runner
// Set the peak mem allocator. This will enable peak memory reporting.
.add_plugin(PeakMemAllocPlugin::new(GLOBAL))
.add_plugin(CacheTrasher::default());
let mut group = runner.new_group();
for (input_name, data) in inputs.iter() {
group.set_input_size(data.len() * std::mem::size_of::<usize>());
group.register_with_input("vec", data, move |data| {
black_box(test_vec(data));
});
group.register_with_input("hashmap", data, move |data| {
black_box(test_hashmap(data));
});
}
group.run();
}
fn main() {
run_bench();
}
Modules§
- plugins
- The module to define custom plugins The plugin system works by registering to events.
- report
- The module to report benchmark results
Structs§
- Bench
Group BenchGroup
is a group of benchmarks wich are executed together.- BenchId
- BenchId is a unique identifier for a benchmark. It has three components:
- Bench
Result - The result of a single benchmark.
- Bench
Runner - The main struct to run benchmarks.
- Config
- Configure the benchmarking options.
- Input
Group InputGroup<Input, OutputValue>
is a collection of benchmarks that are run with the same inputs.- Peak
MemAlloc - An allocator middleware which keeps track of peak memory consumption.
Statics§
- INSTRUMENTED_
SYSTEM - An instrumented instance of the system allocator.
Traits§
- Output
Value - Every bench returns an OutputValue, which can be formatted to a string.
- Peak
MemAlloc Trait - The PeakAllocTrait trait provides a common interface for all allocators.
Functions§
- black_
box - A function that is opaque to the optimizer, used to prevent the compiler from
optimizing away computations in a benchmark.
An identity function that hints to the compiler to be maximally pessimistic about what
black_box
could do.